package com.fingard.dsp.bank.directbank.hnrcb01;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.sql.Connection;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

public class HNRCB01SinglePay extends HNRCB01Base implements ISinglePay {
    private static final String INSERTRECEIPT = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,REQSEQID,BANKREQSEQID,TRANSDATE,RESERVE1) values (?,?,?,?,?,?);";
    private static final String SELECTRECEIPT = "SELECT BANKREQSEQID,TRANSDATE,RESERVE1 FROM REQSEQIDMAPPING WHERE REQSEQID=? and BANKCODE=?;";

    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        Connection conn = FGBiz.getLocalDbConn();
        try {
            JSONObject reqJson = new JSONObject();//发给银行的json报文

            //Body
            JSONObject bodyJson = new JSONObject();
            bodyJson.put("TMFLAG", "2");//本人本行同名转账标志 1-是 2-否
            bodyJson.put("TRANSMODE", p_req1908.singleDetail.sameBnk.equals("1") ? "1" : "2");//转账方式 1-实时到账 2-普通 3-次日到账
            //交易类型 1101-(企业网银)转账汇款-行内转账// 1102-(企业网银)转账汇款-跨行转账// 1146-(企业网银)集团服务-对外付款-行内付款// 1147-(企业网银)集团服务-对外付款-跨行付款
            if("1".equals(p_req1908.singleDetail.rootPay)){
                bodyJson.put("EXTTRANSTYPCD", p_req1908.singleDetail.sameBnk.equals("1") ? "1101" : "1102");
            }else{
                bodyJson.put("EXTTRANSTYPCD", p_req1908.singleDetail.sameBnk.equals("1") ? "1146" : "1147");
            }
            bodyJson.put("PAYERACCTNBR", p_req1908.singleDetail.payAct);//转出账号
            bodyJson.put("PAYERACCTNAME", p_req1908.singleDetail.payName);//付款人名称 本行卡转本行卡必送
            bodyJson.put("PAYEEACCTNBR", p_req1908.singleDetail.recAct);//收款人账号
            bodyJson.put("PAYEEACCTNAME", p_req1908.singleDetail.recName);//收款人名称
            bodyJson.put("PAYEEACCTTYPCD", p_req1908.singleDetail.sameBnk.equals("1") ? "4" : "1");//收款账号类型 交易类型1101/1146时值为4 交易类型为1102/1147时值为1
            bodyJson.put("TRANSAMT", p_req1908.singleDetail.payAmount);//交易金额
            bodyJson.put("PAYEEOPENACCTBANKCODE", p_req1908.singleDetail.cnapsCode);//接收清算行行号
            bodyJson.put("PAYEEBANKNBR", p_req1908.singleDetail.sameBnk.equals("0") ? p_req1908.singleDetail.cnapsCode : "402491000026");//接收方行号 必输 可与开户行号或清算行号相同 本行行号:402491000026
            bodyJson.put("TRANSUSAGE", p_req1908.singleDetail.purpose);//用途
            bodyJson.put("POSTSCRIPT", p_req1908.singleDetail.abstractATS);//备注(存入对账码 )
            String orggrpid = getBankConfig().getMapValueByKey("ORGGRPID", p_req1908.singleDetail.payAct);
            if (StringHelper.isNullOrEmpty(orggrpid)) {
                orggrpid = "0000";
            }
            bodyJson.put("ORGGRPID", orggrpid);//集团ID 非集团账户默认值0000
            bodyJson.put("MCATRANSTYPE", p_req1908.singleDetail.isPrivate.equals("1") ? "1" : "0");//公转私协议标示 0对公1对私
            String ownernbr = getBankConfig().getMapValueByKey("OWNERNBR", p_req1908.singleDetail.payAct);
            if (StringHelper.isNullOrEmpty(orggrpid)) {
                ownernbr = "0000";
            }
            bodyJson.put("OWNERNBR", ownernbr);//集团子账户用户号 非集团账户默认值0000
            reqJson.put("body", bodyJson);


            //head
            HNRCB01Header hnrcb01Header = new HNRCB01Header();
            String customerNum = getBankConfig().getValueAsString("customerNum");//13位客户号
            String indexno = getQryTransID();//11位序列
            hnrcb01Header.reqSeqno = Format.Date8Format.format(new Date()) + customerNum + indexno;
            hnrcb01Header.trsCode = "transferJTOJ";
            //加签字段
            //BRANCHID|USERID|USERNAME|ENTOPERID|ENTOPERNAME|REQSEQNO|TMFLAG|TRANSMODE|EXTTRANSTYPCD|PAYERACCTNBR|PAYERACCTNAME|PAYEEACCTNBR|PAYEEACCTNAME|PAYEEACCTTYPCD|TRANSAMT|PAYEEOPENACCTBANKCODE|PAYEEBANKNBR|TRANSUSAGE|ORGGRPID|MCATRANSTYPE
            StringBuilder signaturedata = new StringBuilder();
            signaturedata.append(bankFront.org).append("|");//BRANCHID 签约机构号
            signaturedata.append(bankFront.loginName).append("|");//USERID 用户号
            signaturedata.append(bankFront.corpNo).append("|");//USERNAME 客户姓名
            signaturedata.append(bankFront.operator).append("|");//ENTOPERID 企网操作员ID
            signaturedata.append(bankFront.userName).append("|");//ENTOPERNAME 企网操作员姓名
            signaturedata.append(hnrcb01Header.reqSeqno).append("|");//REQSEQNO 流水号
            signaturedata.append(bodyJson.get("TMFLAG")).append("|");//TMFLAG 本人本行同名转账标志
            signaturedata.append(bodyJson.get("TRANSMODE")).append("|");//TRANSMODE 转账方式
            signaturedata.append(bodyJson.get("EXTTRANSTYPCD")).append("|");//EXTTRANSTYPCD 交易类型
            signaturedata.append(bodyJson.get("PAYERACCTNBR")).append("|");//PAYERACCTNBR 转出账号
            signaturedata.append(bodyJson.get("PAYERACCTNAME")).append("|");//PAYERACCTNAME 付款人名称
            signaturedata.append(bodyJson.get("PAYEEACCTNBR")).append("|");//PAYEEACCTNBR 收款人账号
            signaturedata.append(bodyJson.get("PAYEEACCTNAME")).append("|");//PAYEEACCTNAME 收款人名称
            signaturedata.append(bodyJson.get("PAYEEACCTTYPCD")).append("|");//PAYEEACCTTYPCD 收款账号类型
            signaturedata.append(bodyJson.get("TRANSAMT")).append("|");//TRANSAMT 交易金额
            signaturedata.append(bodyJson.get("PAYEEOPENACCTBANKCODE")).append("|");//PAYEEOPENACCTBANKCODE 接收清算行行号
            signaturedata.append(bodyJson.get("PAYEEBANKNBR")).append("|");//PAYEEBANKNBR 接收方行号
            signaturedata.append(bodyJson.get("TRANSUSAGE")).append("|");//TRANSUSAGE 用途
            signaturedata.append(orggrpid).append("|");//ORGGRPID 集团ID
            signaturedata.append(bodyJson.get("MCATRANSTYPE"));//MCATRANSTYPE 公转私协议标示
            /**
             * 发送验签报文xml
             */
            XmlTextWriter writerXml = new XmlTextWriter();
            writeSignXml(writerXml, signaturedata.toString());
            String signDateStr[] = sendToBankBySign(writerXml.toXmlString());
            String sign = "";
            if (signDateStr[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(signDateStr[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    if (signDateStr[1].contains("signed_data")) {
                        sign = tmpBkReader.getFirstText("/msg/msg_body/signed_data");
                    }
                    if (StringHelper.isNullOrEmpty(sign)) {
                        //不用xml读取方式，用字符串截取 是因为测试的时候发现如果报错，银行前置
                        //返回报文格式是错误的缺少xml报文头开始标签
                        int errorStart = signDateStr[1].indexOf("<error_no>");
                        int errorEnd = signDateStr[1].indexOf("</error_no>");
                        String errorMsg = signDateStr[1].substring(errorStart + 10, errorEnd);
                        retAts.writeStart();
                        retAts.writeRespCode("-1");
                        retAts.writeRespInfo("加签失败,前置返回:" + errorMsg);
                        retAts.writeEnd();
                        return retAts;
                    }
                } else {
                    retAts.writeStart();
                    retAts.writeRespCode("-1");
                    retAts.writeRespInfo("加签失败：" + tmpSbMsg.toString());
                    retAts.writeEnd();
                    return retAts;
                }
            } else {
                retAts.writeStart();
                retAts.writeRespCode("-1");
                retAts.writeRespInfo("加签失败：" + signDateStr[0]);
                retAts.writeEnd();
                return retAts;
            }
            hnrcb01Header.signaturedata = sign;
            writeCommonHeader(hnrcb01Header, reqJson);

            String[] tmpStrRet = sendToBank(reqJson.toJSONString(), p_req1908.reqHeader.transType, p_req1908.reqHeader.commandCode);
            if (tmpStrRet[0].length() == 0) {
                JSONObject resultObj = JSONObject.parseObject(tmpStrRet[1]);
                //state：返回状态，1代表成功，msg是失败提示
                String state = resultObj.getString("STATUS");
                String msg = resultObj.getString("MSG");
                if (state != null && state.equals("1")) {
                    if (!StringHelper.isNullOrEmpty(resultObj.getString("OVERALLTRANSNBR"))) {
                        //将交易日期，交易类型,银行返回的支付平台流水号存入数据库，支付结果查询时使用
                        String tmpDate = Format.Date8Format.format(new Date());
                        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                        JDBCHelper.update(conn, INSERTRECEIPT, new Object[]{uuid, p_req1908.reqHeader.bankCode, p_req1908.singleDetail.askNumber, resultObj.getString("OVERALLTRANSNBR"), tmpDate, bodyJson.get("EXTTRANSTYPCD")});
                    }
                    tmpRetAtsDetail.respCode = "0";
                    tmpRetAtsDetail.respInfo = msg;
                    tmpRetAtsDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                    tmpRetAtsDetail.transState = state + "+" + resultObj.getString("TRANSSTATUS");
                    tmpRetAtsDetail.payInfoCode = tmpRetAtsDetail.transState;
                } else {
                    tmpRetAtsDetail.respCode = "0";
                    tmpRetAtsDetail.respInfo = msg;
                    tmpRetAtsDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                    tmpRetAtsDetail.transState = state;
                    tmpRetAtsDetail.payInfoCode = tmpRetAtsDetail.transState;
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception ex) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = "单笔转账异常，详情请查看日志！";
            WriteBankLogLn("单笔转账异常:" + ex.getMessage());
        } finally {
            conn.close();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        Connection conn = FGBiz.getLocalDbConn();
        try {
            Map<String, Object> map = JDBCHelper.execQuerySingle(conn, SELECTRECEIPT, new Object[]{p_req1944.askNumber, p_req1944.reqHeader.bankCode});
            if (map.size() == 0) {
                tmpRetAtsDetail.respCode = "0";
                tmpRetAtsDetail.respInfo = "没有该流水映射，请跟银行线下确认支付结果后，手工操作";
                retAts.writeRetDetail(tmpRetAtsDetail);
                return retAts;
            }
            JSONObject reqJson = new JSONObject();//发给银行的json报文
            //Body
            JSONObject bodyJson = new JSONObject();
            bodyJson.put("PAYERACCTNBR", p_req1944.payAct);//付款方账号
            bodyJson.put("PAYEEACCTNBR", p_req1944.recAct);//收款方账号 非必输
            bodyJson.put("STARTDATE", map.get("TRANSDATE").toString());//开始日期
            bodyJson.put("ENDDATE", map.get("TRANSDATE").toString());//结束日期
            bodyJson.put("TRANSSTATUS", "");//交易状态 非必输
            bodyJson.put("EXTTRANSTYPCD", map.get("RESERVE1").toString());//外部转账类型 1101-(企业网银)转账汇款-行内转账 1102-(企业网银)转账汇款-跨行转账 1146-(企业网银)集团服务-对外付款-行内付款 1147-(企业网银)集团服务-对外付款-跨行付款  查询多种类型则用竖线分割：aaaa|bbbb
            bodyJson.put("PAYEEACCTNAME", "");//收款人名称 非必输
            bodyJson.put("PAYEEBANKNAME", "");//收款方行名 非必输
            String orggrpid = getBankConfig().getMapValueByKey("ORGGRPID", p_req1944.payAct);
            if (StringHelper.isNullOrEmpty(orggrpid)) {
                orggrpid = "0000";
            }
            bodyJson.put("ORGGRPID", orggrpid);//集团ID 非集团账户默认值0000
            reqJson.put("body", bodyJson);

            //head
            HNRCB01Header hnrcb01Header = new HNRCB01Header();
            String customerNum = getBankConfig().getValueAsString("customerNum");//13位客户号
            String indexno = getQryTransID();//11位序列
            hnrcb01Header.reqSeqno = Format.Date8Format.format(new Date()) + customerNum + indexno;
            hnrcb01Header.trsCode = "transferQuery";
            //加签字段
            //BRANCHID|USERID|USERNAME|ENTOPERID|ENTOPERNAME|REQSEQNO|PAYERACCTNBR|EXTTRANSTYPCD|ORGGR
            StringBuilder signaturedata = new StringBuilder();
            signaturedata.append(bankFront.org).append("|");//BRANCHID 签约机构号
            signaturedata.append(bankFront.loginName).append("|");//USERID 用户号
            signaturedata.append(bankFront.corpNo).append("|");//USERNAME 客户姓名
            signaturedata.append(bankFront.operator).append("|");//ENTOPERID 企网操作员ID
            signaturedata.append(bankFront.userName).append("|");//ENTOPERNAME 企网操作员姓名
            signaturedata.append(hnrcb01Header.reqSeqno).append("|");//REQSEQNO 流水号
            signaturedata.append(bodyJson.get("PAYERACCTNBR")).append("|");//PAYERACCTNBR 付款方账号
            signaturedata.append(bodyJson.get("EXTTRANSTYPCD")).append("|");//EXTTRANSTYPCD 外部转账类型
            signaturedata.append(orggrpid);//ORGGR 集团ID
            /**
             * 发送验签报文xml
             */
            XmlTextWriter writerXml = new XmlTextWriter();
            writeSignXml(writerXml, signaturedata.toString());
            String signDateStr[] = sendToBankBySign(writerXml.toXmlString());
            String sign = "";
            if (signDateStr[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(signDateStr[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    if (signDateStr[1].contains("signed_data")) {
                        sign = tmpBkReader.getFirstText("/msg/msg_body/signed_data");
                    }
                    if (StringHelper.isNullOrEmpty(sign)) {
                        //不用xml读取方式，用字符串截取 是因为测试的时候发现如果报错，银行前置
                        //返回报文格式是错误的缺少xml报文头开始标签
                        int errorStart = signDateStr[1].indexOf("<error_no>");
                        int errorEnd = signDateStr[1].indexOf("</error_no>");
                        String errorMsg = signDateStr[1].substring(errorStart + 10, errorEnd);
                        retAts.writeStart();
                        retAts.writeRespCode("-1");
                        retAts.writeRespInfo("加签失败,前置返回:" + errorMsg);
                        retAts.writeEnd();
                        return retAts;
                    }
                } else {
                    retAts.writeStart();
                    retAts.writeRespCode("-1");
                    retAts.writeRespInfo("加签失败：" + tmpSbMsg.toString());
                    retAts.writeEnd();
                    return retAts;
                }
            } else {
                retAts.writeStart();
                retAts.writeRespCode("-1");
                retAts.writeRespInfo("加签失败：" + signDateStr[0]);
                retAts.writeEnd();
                return retAts;
            }
            hnrcb01Header.signaturedata = sign;
            writeCommonHeader(hnrcb01Header, reqJson);

            String[] tmpStrRet = sendToBank(reqJson.toJSONString(), p_req1944.reqHeader.transType, p_req1944.reqHeader.commandCode);
            if (tmpStrRet[0].length() == 0) {
                JSONObject resultObj = JSONObject.parseObject(tmpStrRet[1]);
                //state：返回状态，1代表成功，msg是失败提示
                String state = resultObj.getString("STATUS");
                String msg = resultObj.getString("MSG");
                if (state != null && state.equals("1")) {
                    String totalnum = resultObj.get("TOTAL_NUMS").toString();
                    if (!StringHelper.isNullOrEmpty(totalnum) && Integer.parseInt(totalnum) == 0) {
                        tmpRetAtsDetail.respCode = "-1";
                        tmpRetAtsDetail.respInfo = "查询无流水信息";
                    } else {
                        JSONArray resultList = resultObj.getJSONArray("LIST");
                        for (int i = 0; i < resultList.size(); i++) {
                            JSONObject resultListObj = resultList.getJSONObject(i);
                            tmpRetAtsDetail.respCode = "0";
                            tmpRetAtsDetail.respInfo = msg;
                            tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
                            if (resultListObj.get("OVERALLTRANSNBR").equals(map.get("BANKREQSEQID").toString())) {
                                String transstatus = resultListObj.getString("TRANSSTATUS");
                                tmpRetAtsDetail.transState = state + "+" + transstatus;
                                tmpRetAtsDetail.payInfoCode = tmpRetAtsDetail.transState;
                                if (transstatus.equals("0")) {
                                    tmpRetAtsDetail.transAmt = resultListObj.getString("TRANSAMT");
                                }
                            }
                        }
                    }
                } else {
                    tmpRetAtsDetail.respCode = "-1";
                    tmpRetAtsDetail.respInfo = msg;
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = "转账结果查询出现异常，详情查看日志";
            WriteBankLogLn("转账结果查询出现异常:" + e.getMessage());
            e.printStackTrace();
        } finally {
            conn.close();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        return null;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        return null;
    }
}
